﻿using DotLiquid.NamingConventions;
using FastCodeGeneration.Entity;
using FastCodeGeneration.IRepository;
using FastCodeGeneration.IService;
using FastCodeGeneration.Repository;
using FastCodeGeneration.Utility;
using NetTaste;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Dm.net.buffer.ByteArrayBuffer;

namespace FastCodeGeneration.Service
{
    public class CodeGeneratorService : ICodeGeneratorService
    {
        private ICodeGeneratorRepository _codeGeneratorRepository;
        private IProjectRepository _projectRepository;
        private ITableRepository _tableRepository;
        private ITableColumnRepository _tableColumnRepository;
        private ITemplateRepository _templateRepository;
        private IModuleRepository _moduleRepository;

        public CodeGeneratorService(ICodeGeneratorRepository codeGeneratorRepository, IProjectRepository projectRepository,
            ITableRepository tableRepository, ITableColumnRepository tableColumnRepository, ITemplateRepository templateRepository,
            IModuleRepository moduleRepository)
        {
            _codeGeneratorRepository = codeGeneratorRepository;
            _projectRepository = projectRepository;
            _tableRepository = tableRepository;
            _tableColumnRepository = tableColumnRepository;
            _templateRepository = templateRepository;
            _moduleRepository = moduleRepository;
        }
        public List<DbTableInfo> GetDbTables(int projectId)
        {
            var project = _projectRepository.SelectById(projectId);
            return _codeGeneratorRepository.GetDbTables(project);
        }

        public List<DbColumnInfo> GetDbTablesColumns(int projectId, string tableName)
        {
            var project = _projectRepository.SelectById(projectId);
            return _codeGeneratorRepository.GetDbTablesColumns(tableName, project);
        }

        public string GetCodeByTemplate(string templateString, object obj)
        {
            DotLiquid.Template template = DotLiquid.Template.Parse(templateString);
            var code = template.Render(DotLiquid.Hash.FromAnonymousObject(obj));
            return code;
        }

        public bool CodeGeneration(int projectId, List<string> tables)
        {
            var paramList = new List<TempldateParam>();
            var project = _projectRepository.SelectById(projectId);
            var moduleList = _moduleRepository.SelectByProjectId(projectId);
            var tableList = _tableRepository.GetTablesByProjectIdAndIds(projectId, tables);
            var tableNames = tableList.Select(e => e.Name).ToList();
            Dictionary<string, List<TableColumn>> columnDictionary = _tableColumnRepository.GetByTableNames(projectId, tableNames);
            foreach (var table in tableList)
            {
                var columns = columnDictionary[table.Name];
                paramList.Add(new TempldateParam
                {
                    Author = project.Author,
                    DateString = DateTime.Now.ToString(project.DateFormat),
                    Company = project.Company,
                    Name = project.Name,
                    TableAlias = table.FieldClassName.Substring(0, 1),
                    Table = table,
                    HasParentId = columns.FirstOrDefault(e => e.Name == "parent_id") != null,
                    TableColumns = columns
                });
            }
            var templateList = _templateRepository.SelectByProjectId(projectId);
            foreach (var item in templateList)
            {
                foreach (var parameter in paramList)
                {
                    DotLiquid.Template.NamingConvention = new CSharpNamingConvention();
                    DotLiquid.Template template = DotLiquid.Template.Parse(item.Body);  // 解析和编译模板
                    var code = template.Render(DotLiquid.Hash.FromAnonymousObject(parameter));
                    if (parameter.Table.ModuleName.IsNotBlank())
                    {
                        var module = moduleList.FirstOrDefault(e => e.Name == parameter.Table.ModuleName);
                        if (module != null)
                        {
                            string ext = string.Empty;
                            if (project.ServerTemplate.ToUpper() == "JAVA")
                            {
                                var entityFilePath = Directory.GetDirectories(module.ModulePath, module.DomainFolder, SearchOption.AllDirectories)
                                    .FirstOrDefault(e => e.Contains(module.Name));

                                var mapperXmlFilePath = string.Empty;
                                var mapperCodeFilePath = string.Empty;
                                var mapperFilePaths = Directory.GetDirectories(module.ModulePath, module.MapperFolder, SearchOption.AllDirectories)
                                    .Where(e => e.Contains(module.Name));
                                foreach (var mapperFilePath in mapperFilePaths)
                                {
                                    if (mapperFilePath.Contains("resources"))
                                    {
                                        var mPath = Directory.GetDirectories(mapperFilePath, module.Name, SearchOption.AllDirectories).FirstOrDefault();
                                        if (mPath != null)
                                        {
                                            mapperXmlFilePath = mPath;
                                        }
                                        mapperXmlFilePath = mapperFilePath;
                                    }
                                    else if (mapperFilePath.Replace(module.ModulePath, "").Contains(module.Name))
                                    {
                                        mapperCodeFilePath = mapperFilePath;
                                    }
                                }

                                var serviceFilePath = Directory.GetDirectories(module.ModulePath, module.ServiceFolder, SearchOption.AllDirectories)
                                    .FirstOrDefault(e => e.Replace(module.ModulePath, "").Contains(module.Name));
                                var serviceImplFilePath = Path.Combine(serviceFilePath, "impl");
                                var controllerFilePath = Directory.GetDirectories(module.ModulePath, module.ControllerFolder, SearchOption.AllDirectories)
                                    .FirstOrDefault(e => e.Replace(module.ModulePath, "").Contains(module.Name));
                                if (item.TemplateKey == "domain")
                                {
                                    var filePath = Path.Combine(entityFilePath, parameter.Table.ClassName + ".java");
                                    File.WriteAllText(filePath, code);
                                }
                                if (item.TemplateKey == "mapper")
                                {
                                    var filePath = Path.Combine(mapperCodeFilePath, parameter.Table.ClassName + "Mapper.java");
                                    if (!File.Exists(filePath))
                                        File.WriteAllText(filePath, code);

                                }
                                if (item.TemplateKey == "mapper_xml")
                                {
                                    var filePath = Path.Combine(mapperXmlFilePath, parameter.Table.ClassName + "Mapper.xml");
                                    if (!File.Exists(filePath))
                                        File.WriteAllText(filePath, code);
                                }
                                if (item.TemplateKey == "service")
                                {
                                    var filePath = Path.Combine(serviceFilePath, parameter.Table.ClassName + "Service.java");
                                    if (!File.Exists(filePath))
                                        File.WriteAllText(filePath, code);
                                }
                                if (item.TemplateKey == "service_impl")
                                {
                                    var filePath = Path.Combine(serviceImplFilePath, parameter.Table.ClassName + "ServiceImpl.java");
                                    if (!File.Exists(filePath))
                                        File.WriteAllText(filePath, code);
                                }
                                if (item.TemplateKey == "controller")
                                {
                                    var filePath = Path.Combine(controllerFilePath, parameter.Table.ClassName + "Controller.java");
                                    if (!File.Exists(filePath))
                                        File.WriteAllText(filePath, code);
                                }
                            }
                            else if (project.ServerTemplate.ToUpper() == "CSharp")
                            {
                                ext = ".cs";
                            }
                        }
                    }
                }
            }
            return true;
        }


        public bool DeleteCode(int projectId, List<string> tables)
        {
            var project = _projectRepository.SelectById(projectId);
            var moduleList = _moduleRepository.SelectByProjectId(projectId);
            var tableList = _tableRepository.GetTablesByProjectIdAndIds(projectId, tables);
            foreach (var table in tableList)
            {
                var module = moduleList.FirstOrDefault(e => e.Name == table.ModuleName) ?? new Module();
                if (project.ServerTemplate.ToUpper() == "JAVA")
                {
                    var entityFilePath = Directory.GetDirectories(module.ModulePath, module.DomainFolder, SearchOption.AllDirectories)
                        .FirstOrDefault(e => e.Contains(module.Name));

                    var mapperXmlFilePath = string.Empty;
                    var mapperCodeFilePath = string.Empty;
                    var mapperFilePaths = Directory.GetDirectories(module.ModulePath, module.MapperFolder, SearchOption.AllDirectories)
                        .Where(e => e.Contains(module.Name));
                    foreach (var mapperFilePath in mapperFilePaths)
                    {
                        if (mapperFilePath.Contains("resources"))
                        {
                            var mPath = Directory.GetDirectories(mapperFilePath, module.Name, SearchOption.AllDirectories).FirstOrDefault();
                            if (mPath != null)
                            {
                                mapperXmlFilePath = mPath;
                            }
                            mapperXmlFilePath = mapperFilePath;
                        }
                        else if (mapperFilePath.Replace(module.ModulePath, "").Contains(module.Name))
                        {
                            mapperCodeFilePath = mapperFilePath;
                        }
                    }
                    var serviceFilePath = Directory.GetDirectories(module.ModulePath, module.ServiceFolder, SearchOption.AllDirectories)
                        .FirstOrDefault(e => e.Replace(module.ModulePath, "").Contains(module.Name));
                    var serviceImplFilePath = Path.Combine(serviceFilePath, "impl");
                    var controllerFilePath = Directory.GetDirectories(module.ModulePath, module.ControllerFolder, SearchOption.AllDirectories)
                        .FirstOrDefault(e => e.Replace(module.ModulePath, "").Contains(module.Name));

                    var domian_file = Path.Combine(entityFilePath, table.ClassName + ".java");
                    if (File.Exists(domian_file))
                        File.Delete(domian_file);


                    var mapper_file = Path.Combine(mapperCodeFilePath, table.ClassName + "Mapper.java");
                    if (File.Exists(mapper_file))
                        File.Delete(mapper_file);


                    var mapper_xml_file = Path.Combine(mapperXmlFilePath, table.ClassName + "Mapper.xml");
                    if (File.Exists(mapper_xml_file))
                        File.Delete(mapper_xml_file);


                    var service_file = Path.Combine(serviceFilePath, table.ClassName + "Service.java");
                    if (File.Exists(service_file))
                        File.Delete(service_file);


                    var service_impl_file = Path.Combine(serviceImplFilePath, table.ClassName + "ServiceImpl.java");
                    if (File.Exists(service_impl_file))
                        File.Delete(service_impl_file);

                    var controller_file = Path.Combine(controllerFilePath, table.ClassName + "Controller.java");
                    if (File.Exists(controller_file))
                        File.Delete(controller_file);

                }
            }

            return true;
        }
    }
}
